package org.summer.generator.writer;

import org.summer.generator.StringUtil;
import org.summer.generator.vo.MethodInfo;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * java文件写入接口实现类抽象父类,实现java文件写入的公用方法
 *
 * @author gvp9132
 * @date 2024/10/26 22:17
 * @since 1.0.0
 */
public abstract class AbstractJavaFileWriter extends AbstractFileWriter {
    protected static final String PACKAGE_PREFIX = "package ";
    protected static final String CLASS_PREFIX = "public class ";
    protected static final String INTERFACE_PREFIX = "public interface ";
    protected static final String IMPORT_PREFIX = "import ";
    protected static final String METHOD_PREFIX = "\tpublic ";
    protected static final String LINE_END = ";";
    protected static final String BLOCK_START = "{";
    protected static final String BLOCK_END = "}";
    protected static final String SEPARATOR = ".";
    protected static final String FIELD_PREFIX = "\tprivate final ";
    protected static final String IMPLEMENTS = " implements ";
    protected static final String EXTEND = " extends ";
    protected static final String METHOD_RETURN_PREFIX = "\t\treturn ";
    protected static final String LOG_PREFIX = "\t\tlog.debug(\"";
    protected static final String LOG_SUFFIX = "\");";
    protected static final String IMPORT_LOMBOK_RAC = "import lombok.RequiredArgsConstructor;";
    protected static final String LOMBOK_RAC = "@RequiredArgsConstructor";
    protected static final String CONTROLLER_QUERY = "query";
    protected static final String CONTROLLER_SAVE = "save";
    protected static final String CONTROLLER_UPDATE = "update";
    protected static final String CONTROLLER_DELETE = "delete";
    protected static final String SERVICE_FIND = "find";
    protected static final String SERVICE_ADD = "add";
    protected static final String SERVICE_MODIFY = "modify";
    protected static final String SERVICE_REMOVE = "remove";
    protected static final String REPOSITORY_APPEND = "append";
    protected static final String REPOSITORY_EDIT = "edit";
    protected static final String REPOSITORY_CANCEL = "cancel";
    protected static final String REPOSITORY_SEARCH = "search";
    protected static final String TAB = "\t";
    protected static final String LINE = "\n";
    protected static final String SPACING = " ";
    protected static final String CLASS_REMARK = "/**\n * %s\n */";
    protected static final String ANNOTATION_OVERRIDE = "\t@Override";

    /**
     * 获取当前文件写入的类的包定义
     *
     * @return 包定义
     */
    protected String getPackageDefinition(String currentPackageName) {
        return PACKAGE_PREFIX +
                project.getBaseName() +
                SEPARATOR +
                project.getGroupName() +
                SEPARATOR +
                project.getModuleName() +
                SEPARATOR +
                currentPackageName +
                LINE_END;
    }

    /**
     * 获取类代码定义
     * @param packageName 当前包名
     */
    protected String getClaasImplDefinition(String packageName) {
        String cn = table.getTableUpperName() + StringUtil.firstLetterUpperCase(packageName);
        String imp = project.getBaseName() + "." +
                project.getGroupName() + "." +
                project.getModuleName() + "." +
                packageName + "." +
                table.getTableUpperName() +  StringUtil.firstLetterUpperCase(packageName);
        addImport(imp);
        return CLASS_PREFIX
                + cn
                + "Impl"
                + IMPLEMENTS
                + cn
                + BLOCK_START;
    }

    /**
     * 获取类代码定义
     * @param packageName 当前包名
     * @param parentClass 父接口名字
     */
    protected String getClaasDefinition(String packageName, String parentClass) {
        return CLASS_PREFIX
                + table.getTableUpperName()
                + StringUtil.firstLetterUpperCase(packageName)
                + IMPLEMENTS
                + parseParentClass(parentClass)
                + BLOCK_START;
    }

    /**
     * 获取接口代码定义
     * @param packageName 当前包名
     * @param parentInterface 父接口类名
     */
    protected String getInterfaceDefinition(String packageName, String parentInterface){
        return INTERFACE_PREFIX
                + table.getTableUpperName()
                + StringUtil.firstLetterUpperCase(packageName)
                + EXTEND + parseParentClass(parentInterface) + BLOCK_START;
    }

    /**
     * 解析需要实现的接口类
     */
    protected String parseParentClass(String parseClass) {
        String[] split = parseClass.split("\\.");
        addImport(parseClass);
        return split[split.length - 1] + "<%s,%s>".formatted(table.getTableUpperName(), table.getIdType());
    }

    /**
     * 获取依赖的类,获取后,依赖类的导入会自动进行
     * <li>根据依赖的类包名解析,如果依赖UserService,则传入service</li>
     *
     * @param dependencyClassPackage 依赖的类包名
     */
    protected String getDependencyClass(String dependencyClassPackage) {
        String className = table.getTableUpperName() + StringUtil.firstLetterUpperCase(dependencyClassPackage);
        String imp = project.getBaseName() + "." +
                project.getGroupName() + "." +
                project.getModuleName() + "." +
                dependencyClassPackage + "." +
                className;
        addImport(imp);
        return className;
    }

    /**
     *  写入方法到文件中
     * @param method 方法信息对象
     * @param previousObject 当前处理类或接口上一层对象 (controller --> service)
     * @param loadMethodName 加载组件的方法名字(在接口中使用此参数)
     */
    protected abstract void writerMethod(MethodInfo method, String previousObject, String loadMethodName);
}
